#include "Field.h"
#include "Table.h"

using namespace QyOrm;

Field::Field() : QObject(nullptr)
{
    self = this;
}

Field::Field(const Field &f) : QObject(nullptr), self(f.self){}

QString Field::createTemplate()
{
    QString extra;
    if(primaryKey){
        extra += " PRIMARY KEY";
    }else{
        if(unique){
            extra += " UNIQUE";
        }
        if(notNull){
            extra += " NOT NULL";
        }
    }
    return fieldName + " %1" + extra;
}

void Field::setTable(Table *table)
{
    this->table = table;
}

QString Field::create()
{
    return createTemplate().arg(createType());
}

QString Field::execute()
{
    return QString("%1=%2").arg(fieldName).arg(select());
}

bool Field::isString()
{
    return false;
}

ForeignField::ForeignField()
{
    fieldType = FieldType::Foreign;
}

QString ForeignField::select()
{
    return data->primaryKey->select();
}

QString ForeignField::createType()
{
    return data->primaryKey->createType();
}

void ForeignField::query(const QVariant &var)
{
    if(var.isNull()){
        isNull = true;
        return;
    }
    QList<Table*> result = table->createTable(table->hashForeign.value(fieldName), var);
    if(result.size() > 0){
        data = result.at(0);
    }
}

bool ForeignField::set(Table *value, bool isWild)//isWild-表示value是否需要指定parent
{
    Table* tmp = data;
    data = value;
    if(isWild){
        data->setParent(this);
    }
    if(!table->isInstance()){
        if(tmp && tmp->parent() == this){
            tmp->setParent(nullptr);
            delete tmp;
        }
        isNull = false;
        return true;
    }
    if(table->update(this)){
        emit modify();
        if(tmp && tmp->parent() == this){
            tmp->setParent(nullptr);
            delete tmp;
        }
        isNull = false;
        return true;
    }else{
        data = tmp;
        if(isWild){
            value->setParent(nullptr);
            delete value;
        }
        return false;
    }
}

Table* ForeignField::get() const{return data;}
ForeignField &ForeignField::operator()(){return *this;}
ForeignField &ForeignField::operator=(const ForeignField &f){this->self = f.self;this->data = f.data;return *this;}
ForeignField &ForeignField::operator=(Table *value)
{
    set(value);
    return *this;
}

#define FIELD_SET(f,t) bool f ::set(const t &value)\
{\
    t tmp = data;\
    data = value;\
    if(!table->isInstance()) {\
        isNull = false;\
        return true;\
    }\
    if(table->update(this)){\
        emit modify();\
        isNull = false;\
        return true;\
    }else{\
        data = tmp;\
        return false;\
    }\
}

StringField::StringField(){fieldType = FieldType::String;}
QString StringField::select(){return QString("'%1'").arg(data);}
QString StringField::createType(){return (" varchar(255)");}
void StringField::query(const QVariant& var){data=var.toString();isNull=var.isNull();}
bool StringField::isString(){return true;}
QString StringField::get() const{return data;}
FIELD_SET(StringField, QString)
StringField &StringField::operator()(){return *this;}
StringField &StringField::operator=(const StringField &f){this->self = f.self;this->data = f.data;return *this;}
StringField &StringField::operator=(const QString &value){set(value);return *this;}

IntegerField::IntegerField(){fieldType = FieldType::Integer;}
QString IntegerField::select(){return QString::number(data);}
QString IntegerField::createType(){return (" integer");}
void IntegerField::query(const QVariant& var){data=var.toInt();isNull=var.isNull();}
int32_t IntegerField::get() const{return data;}
FIELD_SET(IntegerField, int32_t)
IntegerField &IntegerField::operator()(){return *this;}
IntegerField &IntegerField::operator=(const IntegerField &f){this->self = f.self;return *this;}
IntegerField &IntegerField::operator=(const int32_t &value){set(value);return *this;}

DoubleField::DoubleField(){fieldType = FieldType::Double;}
QString DoubleField::select(){return QString::number(data);}
QString DoubleField::createType(){return (" double");}
void DoubleField::query(const QVariant& var){data=var.toDouble();isNull=var.isNull();}
double DoubleField::get() const{return data;}
FIELD_SET(DoubleField, double)
DoubleField &DoubleField::operator()(){return *this;}
DoubleField &DoubleField::operator=(const DoubleField &f){this->self = f.self;return *this;}
DoubleField &DoubleField::operator=(const double &value){set(value);return *this;}

DateTimeField::DateTimeField(){fieldType = FieldType::DateTime;}
QString DateTimeField::select(){return data.toString(datetime_format);}
QString DateTimeField::createType(){return (" datetime");}
void DateTimeField::query(const QVariant& var){data=var.toDateTime();isNull=var.isNull();}
QDateTime DateTimeField::get() const{return data;}
FIELD_SET(DateTimeField, QDateTime)
DateTimeField &DateTimeField::operator()(){return *this;}
DateTimeField &DateTimeField::operator=(const DateTimeField &f){this->self = f.self;return *this;}
DateTimeField &DateTimeField::operator=(const QDateTime &value){set(value);return *this;}

BooleanField::BooleanField(){fieldType = FieldType::Boolean;}
QString BooleanField::select(){return QString::number(int(data));}
QString BooleanField::createType(){return (" integer");}
void BooleanField::query(const QVariant& var){data=var.toBool();isNull=var.isNull();}
bool BooleanField::get() const{return data;}
FIELD_SET(BooleanField, bool)
BooleanField &BooleanField::operator()(){return *this;}
BooleanField &BooleanField::operator=(const BooleanField &f){this->self = f.self;return *this;}
BooleanField &BooleanField::operator=(const bool &value){set(value);return *this;}




